﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;
using System.Windows.Forms;

namespace JqlEditor
{
    internal class JqlInfo
    {
        /// <summary>
        /// 棋盘布局文件（*.jql）头
        /// </summary>
        private static readonly byte[] JQLHeaderBytes = new byte[]
        {
            0x51, 0x51, 0x47, 0x61, 0x6D, 0x65, 0X20, 0X4A, 0x51, 0x4C, 
            0x20, 0x46, 0x69, 0x6C, 0x65, 0x00, 0x57, 0x04, 0x00, 0x00
        };

        public static readonly JqlInfo Default;
        static JqlInfo()
        {
            List<byte> byteList = new List<byte>() 
            { 
                0x51, 0x51, 0x47, 0x61, 0x6D, 0x65, 0x20, 0x4A, 0x51, 0x4C, 
                0x20, 0x46, 0x69, 0x6C, 0x65, 0x00, 0x57, 0x04, 0x00, 0x00 
            };
            byteList.AddRange(new byte[] 
            {
                0x07, 0x0D, 0x05, 0x0D, 0x07, 
                0x04, 0x00, 0x0D, 0x00, 0x04, 
                0x08, 0x09, 0x00, 0x09, 0x08, 
                0x0A, 0x00, 0x06, 0x00, 0x0A,
                0x0C, 0x0B, 0x0B, 0x0B, 0x0C,
                0x03, 0x02, 0x0C, 0x03, 0x03
            });
            Default = new JqlInfo(byteList.ToArray());
        }

        public byte[] HeaderBytes { get; private set; }
        public byte[] LayoutBytes { get; private set; }
        public JqlChessmanCollection ChessmanCollection { get; private set; }

        private bool IsValid(byte[] bs)
        {
            return bs != null && bs.Length == JqlConsts.JqlFileLength;
        }
        public bool Save(string fileName)
        {
            List<byte> byteList = new List<byte>(HeaderBytes);
            byteList.AddRange(ChessmanCollection.ToBytes());

            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Create))
                using (BinaryWriter bw = new BinaryWriter(fs))
                {
                    bw.Write(byteList.ToArray());
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static JqlInfo LoadFrom(string fileName)
        {
            if (!File.Exists(fileName))
            {
                throw new FileNotFoundException("指定的 JQL 文件不存在");
            }
            return new JqlInfo(File.ReadAllBytes(fileName));
        }
        public static JqlInfo FromRandom()
        {
            return new JqlInfo(GenerateRandomLayout());
        }
        private static byte[] GenerateRandomLayout()
        {
            try
            {
                byte[] layout = new byte[30];

                Random random = new Random();

                // 随机生成军旗的位置
                int flagPosition = (random.Next(0, 2) == 0) ? 26 : 28;
                layout[flagPosition] = (byte)ChessmanType.Flag;

                // 随机生成地雷的位置
                List<int> minesPosition = new List<int>();
                for (int position = random.Next(20, 30); minesPosition.Count < 3; position = random.Next(20, 30))
                {
                    if (!minesPosition.Contains(position) && position != flagPosition)
                    {
                        minesPosition.Add(position);
                    }
                }
                foreach (var position in minesPosition)
                {
                    layout[position] = (byte)ChessmanType.Mine;
                }

                // 随机生成炸弹的位置
                List<int> candidateBombsPosition = new List<int> { 5, 7, 9, 10, 11, 13, 14, 15, 17, 19, 20, 21, 23, 24, 25, 27, 29 };
                List<int> bombsPosition = new List<int>();
                for (int i = random.Next(0, candidateBombsPosition.Count); bombsPosition.Count < 2; i = random.Next(0, candidateBombsPosition.Count))
                {
                    int position = candidateBombsPosition[i];
                    if (layout[position] == 0 && !bombsPosition.Contains(position))
                    {
                        bombsPosition.Add(position);
                    }
                }
                foreach (var position in bombsPosition)
                {
                    layout[position] = (byte)ChessmanType.Bomb;
                }

                // 随机生成其它子力的位置
                List<ChessmanType> chessmanTypes = new List<ChessmanType>()
                {
                    ChessmanType.ChiefCommander,
                    ChessmanType.ArmyCommander,
                    ChessmanType.DivisionalCommander,
                    ChessmanType.DivisionalCommander,
                    ChessmanType.BrigadeCommander,
                    ChessmanType.BrigadeCommander,
                    ChessmanType.RegimentalCommander,
                    ChessmanType.RegimentalCommander,
                    ChessmanType.BattalionCommander,
                    ChessmanType.BattalionCommander,
                    ChessmanType.CompanyCommander,
                    ChessmanType.CompanyCommander,
                    ChessmanType.CompanyCommander,
                    ChessmanType.PlatoonCommander,
                    ChessmanType.PlatoonCommander,
                    ChessmanType.PlatoonCommander,
                    ChessmanType.Sapper,
                    ChessmanType.Sapper,
                    ChessmanType.Sapper
                };
                // 修正另外一个大本营的子力
                int platoonPosition = flagPosition == 26 ? 28 : 26;
                bool setPlatoonCommander = false;
                if ((ChessmanType)layout[platoonPosition] == ChessmanType.None)
                {
                    layout[platoonPosition] = (byte)ChessmanType.PlatoonCommander;
                    chessmanTypes.Remove(ChessmanType.PlatoonCommander);
                    setPlatoonCommander = true;
                }

                List<int> chessmansPosition = new List<int>();
                for (int i = random.Next(0, chessmanTypes.Count); chessmansPosition.Count < chessmanTypes.Count; i = random.Next(0, chessmanTypes.Count))
                {
                    if (!chessmansPosition.Contains(i))
                    {
                        chessmansPosition.Add(i);
                    }
                }

                for (int i = 0, pCount = 0; i < JqlConsts.LayoutRowCount; i++)
                {
                    for (int j = 0; j < JqlConsts.LayoutColCount; j++)
                    {
                        if (i > 0 && i < 4 && j > 0 && j < 4 && (i == j || i + j == 4))
                        {
                            continue;
                        }

                        int position = i * JqlConsts.LayoutColCount + j;
                        if (setPlatoonCommander && position == platoonPosition)
                        {
                            continue;
                        }

                        var chessmanType = (ChessmanType)layout[position];
                        if (chessmanType == ChessmanType.None)
                        {
                            layout[position] = (byte)chessmanTypes[chessmansPosition[pCount]];
                            pCount++;
                        }
                    }
                }

                var jqlBytes = new List<byte>();
                jqlBytes.AddRange(JQLHeaderBytes);
                jqlBytes.AddRange(layout);
                return jqlBytes.ToArray();
            }
            catch (Exception)
            {
                throw;
            }
        }

        public JqlInfo(byte[] bytes)
        {
            if (!IsValid(bytes))
            {
                throw new ArgumentException("JQL 文件内容长度不合法");
            }

            HeaderBytes = new byte[JqlConsts.JqlFileHeaderLength];
            Array.Copy(bytes, 0, HeaderBytes, 0, JqlConsts.JqlFileHeaderLength);

            LayoutBytes = new byte[JqlConsts.JqlFileLayoutLength];
            Array.Copy(bytes, JqlConsts.JqlFileHeaderLength, LayoutBytes, 0, JqlConsts.JqlFileLayoutLength);

            ChessmanCollection = new JqlChessmanCollection(this);
        }
    }
}
